//
// Created by DELL on 2023/9/5.
//

// https://runebook.dev/zh/docs/cpp/thread/latch
// latch 类是 std::ptrdiff_t 类型的向下计数器，可用于同步线程。计数器的值在创建时初始化。线程可能会阻塞在锁存器上，直到计数器减为零。
// 不可能增加或重置计数器，这使得锁存器成为一次性屏障。std::latch 的成员函数的并发调用，除了析构函数，不会引入数据竞争。
// 与 std::barrier 不同， std::latch 可以由参与线程多次递减。

#include <functional>
#include <iostream>
#include <latch>
#include <string>
#include <thread>

struct job {
    const std::string name;
    std::string product{"not worked"};
    std::thread action{};
} jobs[] = {{"annika"}, {"buru"}, {"chuck"}};

int main() {

    std::latch work_done{std::size(jobs)};
    std::latch start_clean_up{1};

    auto work = [&](job& my_job) {
        my_job.product = my_job.name + " worked";
        work_done.count_down();
        start_clean_up.wait();
        my_job.product = my_job.name + " cleaned";
    };

    std::cout << "Work starting... \n";
    for (auto& job : jobs) {
        job.action = std::thread{work, std::ref(job)};
    }
    work_done.wait();
    std::cout << "done:\n";
    for (auto const& job : jobs) {
        std::cout << "  " << job.product << '\n';
    }

    std::cout << "Workers cleaning up... ";
    start_clean_up.count_down();
    for (auto& job : jobs) {
        job.action.join();
    }
    std::cout << "done:\n";
    for (auto const& job : jobs) {
        std::cout << "  " << job.product << '\n';
    }
}